﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Flattiverse;
using System.Threading;

namespace Flattiverse
{
    public partial class ChatGUI : Form
    {
        Connector connector;

        UniverseGroup currentUniverse;
        Team currentTeam;
        List<string> commands = new List<string>(new string[] { "/clear" , "/c" , "/undo", "/ud", "/cmdlist", "/?" });
        Thread workerThread;

        public ChatGUI()
        {         
            InitializeComponent();

            try
            {
                connector = new Connector("kriegsviech@web.de", "Flattichat=1337");

                fillDropDownMenu();

                workerThread = new Thread(new ThreadStart(ServerWorker));

                SetStyle(ControlStyles.UserPaint, true);
                SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
                SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            }
            catch (Exception e)
            {
                lConnectionStatus.Text = e.Message;
            }
        }

        private void fillDropDownMenu()
        {
            foreach (UniverseGroup ug in connector.UniverseGroups)
            {
                ToolStripMenuItem item = new ToolStripMenuItem();
                item.Text = ug.Name + " (" + ug.Accounts.ToList().Count + ")";

                item.Tag = ug;

                foreach (Team team in ug.Teams)
                {
                    ToolStripMenuItem subItem = new ToolStripMenuItem();
                    subItem.Text = team.Name;

                    subItem.Tag = team;

                    item.DropDownItems.Add(subItem);

                    subItem.Click += subItem_Click;
                }

                universesToolStripMenuItem.DropDownItems.Add(item);
            }
        }

        private void subItem_Click(object sender, EventArgs e)
        {
            if (sender is ToolStripMenuItem)
            {
                ToolStripMenuItem item = (ToolStripMenuItem)sender;
                ToolStripItem parent = item.OwnerItem;

                if (item.Tag is Team)
                {
                    if (parent.Tag is UniverseGroup)
                        ConnectTo((UniverseGroup)parent.Tag, (Team)item.Tag);
                    else
                        throw new Exception("Error in Menu Creation");
                }
                else
                    throw new Exception("Error in Menu Creation");
            }
        }

        private void ConnectTo(UniverseGroup ug, Team team)
        {
            if (currentUniverse != null)
            {
                try
                {
                    currentUniverse.Part();
                }
                catch { }
            }

            currentUniverse = ug;
            currentTeam = team;

            currentUniverse.Join("dannyd", currentTeam);

            tbChatText.Enabled = true;

            rbMessages.Clear();

            lvUser.Enabled = true;

            timerChat.Start();

            if (!workerThread.IsAlive)
                workerThread.Start();   
        }

        private void sendChatMessage()
        {
            if (tbChatText.Text != "")
                if (currentUniverse != null)
                {
                    if (!IsCommand(tbChatText.Text))
                        try
                        {
                            currentUniverse.Chat(tbChatText.Text);
                        }
                        catch (Exception e)
                        {
                            rbMessages.AppendText(@"/!\ Fehler: " + e.Message + "\n");
                        }
                }
                else
                    rbMessages.AppendText(@"/!\ Fehler: Es wurde keinem Universum beigetreten!");
            else
                rbMessages.AppendText(@"/!\ Fehler: Es kann kein leerer Text verschickt werden!");

            tbChatText.Text = "";
        }

        private bool IsCommand(string text)
        {
            if (text.Substring(0, 1) == "/")
            {
                switch (text)
                {
                    case "/clear":
                    case "/c":
                        rbMessages.Clear();
                        break;

                    case "/undo":
                    case "/ud":
                        rbMessages.Undo();
                        break;

                    case "/cmdlist":
                    case "/?":
                        rbMessages.AppendText("List verfügbarer Commands:\n");
                        foreach (string cmd in commands)
                            rbMessages.AppendText(cmd + "\n");
                        break;

                    default:
                        rbMessages.AppendText("Unbekannter Command: " + text + "\n");
                        break;
                }
                return true;
            }
            return false;
        }

        public void ServerWorker()
        {
            while (true)
            {
                if (currentUniverse != null)
                {
                    currentUniverse.Commit();
                    currentUniverse.PreWait();
                    currentUniverse.Wait();
                }
                Thread.Sleep(1);
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (connector != null)
            {
                if (connector.IsConnected)
                {
                    lConnectionStatus.Text = "Verbindungsstatus: Verbunden";

                    FlattiverseMessage msg;
                    while (connector.NextMessage(out msg))
                        rbMessages.AppendText(msg.ToString() + "\n");

                    if (currentUniverse != null)
                    {
                        lConnectionStatus.Text += " Ping: " + currentUniverse.AvgTickTime.TotalMilliseconds.ToString("F") + " ms";

                        List<string> disconnectedUser = new List<string>();

                        foreach (ListViewItem lvi in lvUser.Items)
                            disconnectedUser.Add(lvi.Text);

                        List<Account> tempList = new List<Account>(currentUniverse.Accounts.ToList());
                        foreach (Account account in tempList)
                        {
                            if (lvUser.Items.ContainsKey(account.Name) == false)
                            {
                                int imageIndex = 0;

                                if (account.SmallAvatar != null)
                                {
                                    Bitmap smallAvatar = account.SmallAvatar;

                                    if (smallAvatar.Size.Width > 16 || smallAvatar.Size.Height > 16)
                                        smallAvatar = new Bitmap(smallAvatar, new Size(16, 16));

                                    lvUser.SmallImageList.Images.Add(account.Name, smallAvatar);
                                    imageIndex = lvUser.SmallImageList.Images.Count - 1;
                                }

                                ListViewItem lvi = lvUser.Items.Add(account.Name, account.Name, imageIndex);

                                lvi.UseItemStyleForSubItems = false;
                                // Kills
                                lvi.SubItems.Add(account.WeeklyScores.KilledEnemyPlayerUnits.ToString(), Color.ForestGreen, lvi.BackColor, lvi.Font);
                                // Deaths
                                lvi.SubItems.Add(account.WeeklyScores.DeathByPlayerUnits.ToString(), Color.MediumVioletRed, lvi.BackColor, lvi.Font);
                                // Ping
                                lvi.SubItems.Add(account.Ping.TotalMilliseconds.ToString("F") + " ms", (account.Ping.TotalMilliseconds < 100) ? Color.ForestGreen : Color.MediumVioletRed, lvi.BackColor, lvi.Font);
                                // Avg Ticks
                                lvi.SubItems.Add(account.AverageCommitTime.TotalMilliseconds.ToString("F") + " ms", (account.AverageCommitTime.TotalMilliseconds < 50) ? Color.ForestGreen : Color.MediumVioletRed, lvi.BackColor, lvi.Font);
                            }
                            else
                            {
                                // Spieler ist noch aktiv
                                disconnectedUser.Remove(account.Name);
                                
                                try
                                {
                                    ListViewItem lvi = lvUser.Items[account.Name];

                                    lvi.SubItems[1].Text = account.WeeklyScores.KilledEnemyPlayerUnits.ToString();
                                    lvi.SubItems[2].Text = account.WeeklyScores.DeathByPlayerUnits.ToString();

                                    lvi.SubItems[3].Text = account.Ping.TotalMilliseconds.ToString("F") + " ms";
                                    lvi.SubItems[3].ForeColor = (account.Ping.TotalMilliseconds < 100) ? Color.ForestGreen : Color.MediumVioletRed;

                                    lvi.SubItems[4].Text = account.AverageCommitTime.TotalMilliseconds.ToString("F") + " ms";
                                    lvi.SubItems[4].ForeColor = (account.AverageCommitTime.TotalMilliseconds < 50) ? Color.ForestGreen : Color.MediumVioletRed;
                                }
                                catch { rbMessages.AppendText(@"/!\ Fehler: Fehler beim Aktualisieren der Statistiken"); }
                            }
                        }

                        foreach (string accountName in disconnectedUser)
                        {
                            lvUser.Items.RemoveByKey(accountName);

                            lvUser.SmallImageList.Images.RemoveByKey(accountName);
                        }

                    }
                }
            }
        }

        #region Connect Menu Click
        private void connectToolStripMenuItem_Click(object sender, EventArgs e)
        {
 
        }
        #endregion

        #region Chat Events
        private void bSendChat_Click(object sender, EventArgs e)
        {
            sendChatMessage();
        }     

        private void rbMessages_TextChanged(object sender, EventArgs e)
        {
            try
            {
                rbMessages.SelectionStart = rbMessages.TextLength;
                rbMessages.ScrollToCaret();
                rbMessages.Refresh();
            }
            catch { Console.WriteLine("Error"); }
        }

        private void tbChatText_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                sendChatMessage();
        }

        private void tbChatText_TextChanged(object sender, EventArgs e)
        {
            if (tbChatText.Text == "")
                bSendChat.Enabled = false;
            else
                bSendChat.Enabled = true;
        }
        #endregion

        private void ChatGUI_FormClosed(object sender, FormClosedEventArgs e)
        {
            workerThread.Abort();

            connector.Close();


        }

        private void ChatGUI_Load(object sender, EventArgs e)
        {

        }

    }
}
